package cn.wolfcode.business.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import cn.wolfcode.business.util.DateUtil;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.wolfcode.business.mapper.BusBpmnInfoMapper;
import cn.wolfcode.business.domain.BusBpmnInfo;
import cn.wolfcode.business.service.IBusBpmnInfoService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

/**
 * 流程定义明细Service业务层处理
 *
 * @author lyh
 * @date 2025-09-25
 */
@Service
public class BusBpmnInfoServiceImpl implements IBusBpmnInfoService {
    @Autowired
    private BusBpmnInfoMapper busBpmnInfoMapper;
    @Autowired
    private RepositoryService repositoryService;


    /**
     * 查询流程定义明细
     *
     * @param id 流程定义明细主键
     * @return 流程定义明细
     */
    @Override
    public BusBpmnInfo selectBusBpmnInfoById(Long id) {
        return busBpmnInfoMapper.selectBusBpmnInfoById(id);
    }

    /**
     * 查询流程定义明细列表
     *
     * @param busBpmnInfo 流程定义明细
     * @return 流程定义明细
     */
    @Override
    public List<BusBpmnInfo> selectBusBpmnInfoList(BusBpmnInfo busBpmnInfo) {
        String endDeployTime = (String) busBpmnInfo.getParams().get("endDeployTime");

        //将获取的String类型转为Date类型
        Date endTime = DateUtil.parseDate(endDeployTime, "yyyy-MM-dd");
        //调用工具类弹出时间  进行+1天 -1天 进行时间转换
        Date changedDate = DateUtil.changeDate(endTime, Calendar.DAY_OF_YEAR, 1);
        Date time = DateUtil.changeDate(changedDate, Calendar.MILLISECOND, -1);
        String endDate = DateUtil.Date2String(time, "yyyy-MM-dd HH:mm:ss");
        busBpmnInfo.getParams().put("endDeployTime", endDate);
        return busBpmnInfoMapper.selectBusBpmnInfoList(busBpmnInfo);
    }

    /**
     * 新增流程定义明细
     *
     * @param busBpmnInfo 流程定义明细
     * @return 结果
     */
    @Override
    public int insertBusBpmnInfo(BusBpmnInfo busBpmnInfo) {
        return busBpmnInfoMapper.insertBusBpmnInfo(busBpmnInfo);
    }

    /**
     * 修改流程定义明细
     *
     * @param busBpmnInfo 流程定义明细
     * @return 结果
     */
    @Override
    public int updateBusBpmnInfo(BusBpmnInfo busBpmnInfo) {
        return busBpmnInfoMapper.updateBusBpmnInfo(busBpmnInfo);
    }

    /**
     * 批量删除流程定义明细
     *
     * @param ids 需要删除的流程定义明细主键
     * @return 结果
     */
    @Override
    public int deleteBusBpmnInfoByIds(Long[] ids) {
        return busBpmnInfoMapper.deleteBusBpmnInfoByIds(ids);
    }

    /**
     * 删除流程定义明细信息
     *
     * @param id 流程定义明细主键
     * @return 结果
     */
    @Override
    public int deleteBusBpmnInfoById(Long id) {
        if(id == null){
            throw new RuntimeException("参数不能为空");
        }
        BusBpmnInfo bpmnInfo = this.selectBusBpmnInfoById(id);
        if(bpmnInfo == null){
            throw new RuntimeException("参数错误");
        }
        //根据流程定义的key查询流程定义对象
      ProcessDefinition processDefinition =  repositoryService.createProcessDefinitionQuery()
               .processDefinitionKey(bpmnInfo.getProcessDefinitionKey())
              .processDefinitionVersion(bpmnInfo.getVersion())
               .singleResult();
        //删除部署  级联删除
        repositoryService.deleteDeployment(processDefinition.getDeploymentId(), true);
        //删除流程定义明细
        return busBpmnInfoMapper.deleteBusBpmnInfoById(id);
    }

    /**
     * 流程定义明细
     *
     * @param file     流程文件
     * @param bpmnType 流程类型
     * @param info     流程的信息
     * @return
     */
    @Override
    @Transactional

    public int deploy(MultipartFile file, Integer bpmnType, String info) throws IOException {
        //非空校验认证
        if (file == null || bpmnType == null || info == null) {
            throw new RuntimeException("参数不能为空");
        }
        //验证文件类型
        //获取文件名
        String originalFilename = file.getOriginalFilename();
        //获取文件名字的后缀 也就是扩展名
        String extension = FilenameUtils.getExtension(originalFilename);
        if (!("bpmn".equals(extension) || "xml".equals(extension))) {
            throw new RuntimeException("文件格式错误,必须是XML和bpmn");
        }
        //验证大小
        long maxSize = 1024 * 1024 * 10; //10M
        if (file.getSize() > maxSize) {
            throw new RuntimeException("文件过大,不能超过10MB");
        }
        //部署操作
        Deployment deploy = repositoryService.createDeployment()
                .addInputStream(originalFilename, file.getInputStream())
                .deploy();
        //根据部署信息查询流程定义对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploy.getId())
                .singleResult();

// 添加null检查
        if (processDefinition == null) {
            List<ProcessDefinition> allDefs = repositoryService.createProcessDefinitionQuery()
                    .deploymentId(deploy.getId())
                    .list();

            if (allDefs.isEmpty()) {
                throw new RuntimeException("BPMN文件部署成功但未生成流程定义，请检查文件格式");
            } else {
                processDefinition = allDefs.get(0);
            }
        }
        //封装 数据 BpmnInfo 对象
        BusBpmnInfo bpmnInfo = new BusBpmnInfo();
        bpmnInfo.setBpmnLabel(originalFilename);
        bpmnInfo.setBpmnType((bpmnType));
        bpmnInfo.setProcessDefinitionKey(processDefinition.getKey());
        bpmnInfo.setDeployTime(deploy.getDeploymentTime());
        bpmnInfo.setVersion(processDefinition.getVersion());
        bpmnInfo.setInfo(info);
        //插入到数据库中
        return busBpmnInfoMapper.insertBusBpmnInfo(bpmnInfo);
    }

    /**
     * 读取资源
     *
     * @param id
     * @param type
     * @return
     */
    @Transactional
    @Override
    public InputStream readResource(Long id, String type) {
        //参数校验
        if (id == null || type == null) {
            throw new RuntimeException("参数错误");
        }
        //根据ID查询BpmnInfo对象
        BusBpmnInfo bpmnInfo = this.selectBusBpmnInfoById(id);
        if (bpmnInfo == null) {
            throw new RuntimeException("流程定义不存在");
        }
        // 在获取到其中的key  version
        String processDefinitionKey = bpmnInfo.getProcessDefinitionKey();
        Integer version = bpmnInfo.getVersion();
        //查询流程定义对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(processDefinitionKey)
                .processDefinitionVersion(version)
                .singleResult();

        // 检查流程定义是否存在
        if (processDefinition == null) {
            throw new RuntimeException("流程定义在引擎中不存在，key: " + processDefinitionKey + ", version: " + version);
        }

        //根据type 判断查询的资源是什么
        if ("xml".equalsIgnoreCase(type)) {
            //通过流程定义对象获取资源名称和部署ID
            String resourceName = processDefinition.getResourceName();
            String deploymentId = processDefinition.getDeploymentId();
            //通过 activit7 去获取文件的输入流
            return repositoryService.getResourceAsStream(deploymentId, resourceName);

        }
        if ("png".equalsIgnoreCase(type)) {
            //获取图片名称
            String diagramResourceName = processDefinition.getDiagramResourceName();
            //创建Activiti7插件 插件之前导入过 promxl
            DefaultProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
            //  使用reposioryService 根据流程定义ID 获取 BpmnMono模型
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());

            return processDiagramGenerator.generateDiagram(
                  bpmnModel,
                    Collections.emptyList(),
                    Collections.emptyList(),
                    "宋体",
                    "宋体",
                    "宋体"
            );
        }
        return null;  // 返回null
    }
// 查询流程定义明细
    @Override
    public BusBpmnInfo selectBusBpmnInfoByType(Integer bpmnType) {
        return   busBpmnInfoMapper.selectBusBpmnInfoByType(bpmnType);
    }
}
